'''
在封装中
一个下划线_表示受保护的，只能被自身以及子类使用。但是类外如果想强行访问，也有方法
两个下划线__表示这个是私有的，不能被外界使用
首尾都有__则表示特殊的函数如我们的__init__
'''

class Student :  #创建一个类
    def __init__(self,name,age,gender):
        self._name = name #这里表示这个函数中的name是被保护的
        self.__age = age #这里表示age这个是私有的，外界并不能使用
        self.gender=gender #这个是普通实例，访问权限是最大的
    #这里就是一个受保护的方法
    def _fun1 (self): #实例方法：类中定义的方法，需要有一个self参数
        print("只有本类与子类可以使用")
    def __fun2 (self):
        print("只有本类可以使用，是私有的")
    def show (self):
        # 类中普通的方法可以访问受保护的与私有的都可以
        self._fun1()
        self.__fun2()
        print( self._fun1(),self.__fun2())

student1=Student("黄思瑜",19,"女")
print(student1._name) #这里注意访问的_name,不要忘记带那个下划线
#print(student1.__age) 这里是访问不到的，要用一个特殊的方法，下面有
student1._fun1()
# student1.__fun2() 这里是访问不到的，要用一个特殊的方法，下面有

#访问私有得变量或者方法，需要用 对象名._类名__方法名or变量   注意啊这里只有对象名调用一个点，后面都没有点
print(student1._Student__age) #这个是不推荐得，因为我们一般将方法转化属性去使用
student1._Student__fun2()
print(dir(student1))
'''
这个调用可以显示出这个对象所有得属性，可以知道所有得私有属性以_Student__age这个格式存储，所以可以这样调用
'''
'''
用@property修饰
方法转化成属性去使用，只能使用这个方法得值，不能改变他的值
属性使用: 对象名.属性  直接使用
用@property.setter修饰
方法转化成属性的同时可以直接的修改属性值，如果没有setter是不能修改的
'''
class cat:
    def __init__(self,name,color,gender):
        self.color = color
        self.name = name
        self.__gender = gender
    @property
    def gender(self):
        return self.__gender

    @gender.setter
    def gender(self,value): #这里是一个有参数的函数，传进来性别，判断
        if value != "男" and value != "女":
            print("性别输入有误，已默认为女，请重新输入！")
            self.__gender='女'
        else:
            self.__gender=value

cat1=cat("小小","黄色","男")
print(cat1.name,"的颜色是",cat1.color,"性别是",cat1.gender)
cat1.gender='其他'
print(cat1.name,"的颜色是",cat1.color,"性别是",cat1.gender)